package com.lvmama.rhino.web;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lvmama.rhino.entity.StatisticCodesConditionVO;
import com.lvmama.rhino.enums.CommonType;
import com.lvmama.rhino.pojo.StatisticCode;
import com.lvmama.rhino.service.StatisticCodeService;
import com.lvmama.rhino.service.impl.comment.RedisServiceImpl;
import com.lvmama.rhino.utils.Constants;
import com.lvmama.rhino.utils.EncryptionKey;
import com.lvmama.rhino.utils.JedisTemplate;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
@RequestMapping("statisticCode")
public class StatisticCodeController {

    @Autowired
    private StatisticCodeService statisticCodeService;
    @Autowired
    private RedisServiceImpl redisService;

    /**
     * code码列表列表
     *
     * @param model
     * @param sc
     * @param message
     * @return
     */
    @RequiresPermissions("sys:statisticCode:view")
    @RequestMapping("list")
    public String list(ModelMap model, StatisticCodesConditionVO sc, String message) {
        PageInfo<StatisticCode> page = statisticCodeService.getAllList(sc);
        model.addAttribute("statisticCodesConditionVO", sc);
        model.addAttribute("page", page);
        model.addAttribute("statisticCodes", page.getList());
        model.addAttribute("message", message);
        return "application/statisticCodeList";
    }

    /**
     * code码树形展示
     *
     * @param model
     * @return
     */
    @RequestMapping("new")
    public String newStatisticCode(Model model, String message) {
        model.addAttribute("message", message);
        String str = treeviewStr();
        model.addAttribute("treeview", str);
        return "application/statisticCodeForm";
    }

    /**
     * 获取treeview的数据
     *
     * @return
     */
    public String treeviewStr() {
        //获取统计code码所有数据
        List<StatisticCode> statisticCodes = statisticCodeService.getStatisticCodeList();
        JSONArray statisticCodeJson1 = new JSONArray();
        //通过循环遍历拼接json数据
        for (StatisticCode statisticCode : statisticCodes) {
            try{
                if (statisticCode != null && statisticCode.getIsAdd() != null && !"".equals(statisticCode.getIsAdd())){
                    String isAdd = statisticCode.getIsAdd();
                    String type = null;
                    if ("1".equals(isAdd)) {
                        type = "folder";
                    } else {
                        type = "item";
                    }
                    JSONObject node = new JSONObject();
                    node.put("id", statisticCode.getId());
                    node.put("name", statisticCode.getName());
                    node.put("parentId", statisticCode.getParentId());
                    node.put("type", type);
                    node.put("code", statisticCode.getCode());
                    statisticCodeJson1.add(node);
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }

        for (int i = 0; i < statisticCodeJson1.size(); i++) {
            JSONObject obj1 = statisticCodeJson1.getJSONObject(i);
            JSONObject objName = new JSONObject();
            JSONArray arr1 = new JSONArray();
            for (int j = 0; j < statisticCodeJson1.size(); j++) {
                JSONObject obj2 = statisticCodeJson1.getJSONObject(j);
                if (obj1.get("id").equals(obj2.get("parentId"))) {
                    objName.put(obj2.get("name").toString(), obj2);
                }
            }
            arr1.add(objName);
            obj1.put("children", arr1);
        }
        JSONArray arr = new JSONArray();
        JSONObject objName = new JSONObject();
        for (int i = 0; i < statisticCodeJson1.size(); i++) {
            JSONObject obj1 = statisticCodeJson1.getJSONObject(i);
            if (obj1.get("parentId") == null) {
                objName.put(obj1.get("name").toString(), obj1);
            }
        }
        arr.add(objName);
        String str = arr.toJSONString();
        return str;
    }


    /**
     * 获取jQueryEasyUI的tree的数据
     *
     * @param parentName
     * @return
     */
    @RequestMapping(value = "treegrid", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String statisticCode(String parentName) throws Exception {
        List<StatisticCode> statisticCodes;
        StatisticCode statisticParentCode = new StatisticCode();
        if ("all".equals(parentName)) {
            //查询所有code码信息
            statisticCodes = statisticCodeService.getStatisticCodeList();
        } else {
            statisticParentCode.setName(parentName);
            //根据条件查询code对象
            statisticParentCode = statisticCodeService.selectStatisticCode(statisticParentCode);
            //根据父级code码，查询子级对象
            if ("4".equals(statisticParentCode.getCode())) {
                statisticCodes = statisticCodeService.queryChildCodeListByParentId(statisticParentCode.getId());
                statisticCodes.add(statisticParentCode);
            } else {
                statisticCodes = statisticCodeService.getParentAndChildrenLikeCodeObj(statisticParentCode.getCode());
            }
        }
        
        //List<StatisticCode> statisticCodes = statisticCodeService.getStatisticCodeList();
        JSONArray statisticCodeJsons = new JSONArray();
        
        //拼接json数据
        if (statisticCodes != null && statisticCodes.size() > 0){
        	for (StatisticCode statisticCode : statisticCodes) {
        		if (statisticCode != null && statisticCode.getIsAdd() != null && !"".equals(statisticCode.getIsAdd())){
        			String isAdd = "1".equals(statisticCode.getIsAdd()) ? "允许" : "不允许";
        			StatisticCode codeObj = statisticCode.getParent();
        			String parent = null;
        			if (codeObj != null) {
        				parent = codeObj.getName();
        			}
        			JSONObject node = new JSONObject();
        			node.put("id", statisticCode.getId());
        			node.put("name", statisticCode.getName());
        			node.put("enName", statisticCode.getEnName());
        			node.put("parentId", statisticCode.getParentId());
        			node.put("parent", parent);
        			node.put("code", statisticCode.getCode());
        			node.put("isAdd", isAdd);
        			node.put("codeType", statisticCode.getCodeType());
        			node.put("codeTypeLevel", statisticCode.getCodeTypeLevel());
        			statisticCodeJsons.add(node);
        		}
        	}
        }
        
        if (statisticCodeJsons != null ){
        	for (int i = 0; i < statisticCodeJsons.size(); i++) {
        		JSONObject obj1 = statisticCodeJsons.getJSONObject(i);
        		JSONArray arr1 = new JSONArray();
        		for (int j = 0; j < statisticCodeJsons.size(); j++) {
        			JSONObject obj2 = statisticCodeJsons.getJSONObject(j);
        			if (obj1.get("id") != null && obj1.get("id").equals(obj2.get("parentId"))) {
        				arr1.add(obj2);
        			}
        		}
        		obj1.put("children", arr1);
        	}
        }
        JSONArray arr = new JSONArray();
        //当查询所有code数据时
        if ("all".equals(parentName) ) {
        	if (statisticCodeJsons != null){
        		for (int i = 0; i < statisticCodeJsons.size(); i++) {
        			JSONObject obj1 = statisticCodeJsons.getJSONObject(i);
        			if (obj1.get("parentId") == null) {
        				arr.add(obj1);
        			}
        		}
        	}
            //查询指定code码数据时
        } else {
        	if (statisticCodeJsons != null){
        		for (int i = 0; i < statisticCodeJsons.size(); i++) {
        			JSONObject obj1 = statisticCodeJsons.getJSONObject(i);
        			String id = obj1.get("id").toString();
        			if (id != null && id.equals(statisticParentCode.getId().toString())) {
        				arr.add(obj1);
        			}
        		}
        	}
        }
        return arr.toJSONString();
    }

    /**
     * 编辑code码
     *
     * @param codeId
     * @return
     */
    @RequiresPermissions("sys:statisticCode:edit")
    @RequestMapping("/edit")
    @ResponseBody
    public Object edit(String codeId) {
        Map<String, Object> result = getResult();
        StatisticCode statisticCode = new StatisticCode();
        statisticCode.setId(Integer.parseInt(codeId));
        //根据条件查询code对象
        statisticCode = statisticCodeService.selectStatisticCode(statisticCode);
        //根据id查询子节点
        List<StatisticCode> childCodeList = statisticCodeService.queryChildCodeListByParentId(statisticCode.getId());
        //是否允许编辑前端isAdd选项
        boolean showIsAdd = false;
        if (childCodeList != null && childCodeList.size() != 0) {
            showIsAdd = true;
        }
        if (statisticCode != null) {
            result.put("code", "1");
            result.put("statisticCode", statisticCode);
            result.put("parentCode", statisticCode.getParent());
            result.put("showIsAdd", showIsAdd);
        }
        return result;
    }


    /**
     * 操作code码操作
     *
     * @param statisticCode
     * @param parentId
     * @return
     */
    @RequiresPermissions("sys:statisticCode:edit")
    @RequestMapping("save")
    @ResponseBody
    public Object saveCode(StatisticCode statisticCode, Integer parentId, boolean isNew, String nameBak) {
        StatisticCode parentCode = new StatisticCode();
        parentCode.setId(parentId);
        statisticCode.setParent(parentCode);
        Map<String, Object> result = getResult();
        //当编辑code码name为修改时，则传递为false;若新增code码和编辑code码时修改了name，则传递为true
        if (isNew) {
            //判断code码的name是否已存在
            int isExist = statisticCodeService.getCountForName(statisticCode.getName()) == 0 ? 0 : statisticCodeService.getCountForName(statisticCode.getName());
            if (isExist != 0) {
                result.put("code", 1);
                result.put("msg", "操作失败,该中文名称的code码已存在");
                return result;
            }
        }
        //操作code码信息
        int flag = statisticCodeService.operationCode(statisticCode);
        JedisTemplate jtw = JedisTemplate.getWriterInstance();
        if (flag == 1) {
            jtw.del("codeName_" + nameBak);
            result.put("code", 1);
            result.put("msg", "code码操作成功");
        } else {
            result.put("code", 1);
            result.put("msg", "code码操作失败");
        }
        return result;
    }


    /**
     * 操作code码操作
     *
     * @param codeInfo
     * @return
     */
    @RequiresPermissions("sys:statisticCode:edit")
    @RequestMapping("saveCode")
    @ResponseBody
    public Object saveCodeTree(String codeInfo) {
        Map<String, Object> result = getResult();
        String codeStr = StringEscapeUtils.unescapeXml(codeInfo);
        JSONObject code = JSONObject.parseObject(codeStr);
        StatisticCode statisticCode = new StatisticCode();
        statisticCode.setId((Integer) code.get("id"));
        statisticCode.setName(code.get("name").toString());
        statisticCode.setEnName(code.get("enName").toString());
        statisticCode.setCode(code.get("code").toString());
        String parentId = null;
        if (code.get("parentId") != null) {
            parentId = code.get("parentId").toString();
        }
        int flag = 0;
        if (StringUtils.isNotEmpty(parentId) && ("15".equals(parentId) || "434".equals(parentId))) {
            flag = statisticCodeService.updateOtherCode(statisticCode);
        } else {
            flag = statisticCodeService.updateCode(statisticCode);
        }

        if (flag == 1) {
            result.put("statisticCodes", treeviewStr());
            result.put("code", 1);
            result.put("msg", "code码操作成功");
        } else {
            result.put("code", 1);
            result.put("msg", "code码操作失败");
        }
        return result;
    }


    /**
     * 随机生成code码
     *
     * @param parentCode
     * @return
     */
    @RequestMapping("createCode")
    @ResponseBody
    public Object createCode(String parentCode) {
        Map<String, Object> result = getResult();
        //获取父级code码的第一个字符
        String firstStr = parentCode.substring(0, 1);
        //查询前缀为parentCode的code码信息
        List<String> codesList = null;
        if ("3zhTi".equals(parentCode)) {
            codesList = statisticCodeService.getZhtiLikeCode(parentCode);

        } else if ("4".equals(parentCode)) {
            codesList = statisticCodeService.getPitLikeCode();
        } else {
            codesList = statisticCodeService.getLikeCodes(parentCode);
        }

        EncryptionKey encryptionKey = new EncryptionKey();

        //父级code码的长度
        int digits = parentCode.length();
        //随机数的位数(后面通过调用getCode(count)方法生成随机数)
        int count = 0;
        String codeType = "";
        //code码类型级别
        String codeTypeLevel = "";
        if (EncryptionKey.CHANNEL_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为1
            //code码类型为渠道(Channel)
            codeType = EncryptionKey.CODETYPE_CHANNEL;
            switch (digits) {
                case 1:
                    count = 1;
                    codeTypeLevel = "C2";
                    break;
                case 2:
                    codeTypeLevel = "C3";
                    //内部渠道code码为"11"
                    if ("11".equals(parentCode)) {
                        count = 4;
                    } else {
                        count = 1;
                    }
                    break;
                case 3:
                    codeTypeLevel = "C4";
                    count = 3;
                    break;
                default:
                    break;
            }
        } else if (EncryptionKey.DEVICE_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为2
            codeTypeLevel = "D2";
            //code码类型为渠道(Device)
            codeType = EncryptionKey.CODETYPE_DEVICE;
            count = 3;
        } else if (EncryptionKey.PAGE_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为3
            //code码类型为渠道(Page)
            codeType = EncryptionKey.CODETYPE_PAGE;
            switch (parentCode) {
                case "3":
                    codeTypeLevel = "P2";
                    count = 4;
                    break;
                default:
                    codeTypeLevel = "P3";
                    count = 3;
                    break;
            }
        }
        //验证是否存在，若存在，则重新生成code码
        String codeData = encryptionKey.validateCode(codesList, parentCode, count);
        result.put("code", "1");
        result.put("msg", codeData);
        result.put("codeType", codeType);
        result.put("codeTypeLevel", codeTypeLevel);
        return result;
    }


    /**
     * 随机生成看坑位code码
     *
     * @param page
     * @param pitName
     * @return
     */
    @RequestMapping("createPitCode")
    @ResponseBody
    public Object createPitCode(String page, String pitName) {
        Map<String, Object> result = getResult();
        String codeType = "Pit";
        String codeTypeLevel = "K2";
        StatisticCode statisticCode = new StatisticCode();
        statisticCode.setName(page);
        statisticCode.setIsAdd(CommonType.DISSHOW.getStringValue());
        statisticCode = statisticCodeService.selectStatisticCode(statisticCode);
        String code = statisticCode.getCode();
        String pageTag = code.substring(code.length() - 3);

        //验证是否存在，若存在，不用重新生成
        StatisticCode statisticCode2 = new StatisticCode();
        statisticCode2.setCode(pageTag + pitName);
        statisticCode2 = statisticCodeService.selectStatisticCode(statisticCode2);
        if (statisticCode2 != null) {
            result.put("code", "-1");
            result.put("errorMsg", "该坑位已存在！");
            return result;
        }
        result.put("code", "1");
        result.put("msg", pageTag + pitName);
        result.put("codeType", codeType);
        result.put("codeTypeLevel", codeTypeLevel);
        return result;
    }

    /**
     * 查询父级code码信息
     *
     * @return
     */
    @RequiresPermissions("sys:statisticCode:edit")
    @RequestMapping("/getParent")
    @ResponseBody
    public Object getParent(String nodeHtml) throws Exception {
        Map<String, Object> result = getResult();
        StatisticCode statisticCode = new StatisticCode();
        statisticCode.setName(nodeHtml);
        statisticCode.setIsAdd(CommonType.ENSHOW.getStringValue());
        statisticCode = statisticCodeService.selectStatisticCode(statisticCode);
        //新增坑位时查询出所有的页面
        List<String> pageAll;
        if ("坑位".equals(nodeHtml)) {
            //使用Redis缓存，提升效率  //
        	/**修改可以名称由原来的rhino_statistic_code_page_son 改成rhino_statistic_code_page_sons
        	 * 原来的可以存储的值只有首页
        	 * */
            String key = "rhino_statistic_code_page_sons";
            String pageSonValue = redisService.getObjectValue(key);
            if (StringUtils.isNotBlank(pageSonValue)) {
                pageAll = new Gson().fromJson(pageSonValue, new TypeToken<List<String>>() {
                }.getType());
            } else {
                pageAll = statisticCodeService.getPageAllSonName();
                redisService.setValueExpire(key, pageAll, Constants.TIMEOUT);
            }
            statisticCode.setPageList(pageAll);
        }
        if (statisticCode != null) {
            String parentCode = statisticCode.getCode();
            if (!"4".equals(parentCode)) {
                //获取父级code码的第一个字符
                String firstStr = parentCode.substring(0, 1);
                //查询前缀为parentCode的code码信息
                List<String> codesList = null;
                if ("3zhTi".equals(parentCode)) {
                    codesList = statisticCodeService.getZhtiLikeCode(parentCode);
                } else {
                    codesList = statisticCodeService.getLikeCodes(parentCode);
                }
                //父级code码的长度
                int digits = parentCode.length();
                //随机数的位数(后面通过调用getCode(count)方法生成随机数)
                int count = 0;
                if (EncryptionKey.CHANNEL_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为1
                    switch (digits) {
                        case 1:
                            count = 1;
                            break;
                        case 2:
                            //内部渠道code码为"11"
                            if ("11".equals(parentCode)) {
                                count = 4;
                            } else {
                                count = 1;
                            }
                            break;
                        case 3:
                            count = 3;
                            break;
                        default:
                            break;
                    }
                } else if (EncryptionKey.DEVICE_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为2
                    count = 3;
                } else if (EncryptionKey.PAGE_FIRST_CHARACTER.equals(firstStr)) {//渠道级别的首字符为3
                    switch (parentCode) {
                        case "3":
                            count = 4;
                            break;
                        default:
                            count = 3;
                            break;
                    }
                }

                if (codesList == null || codesList.size() >= Math.pow(EncryptionKey.s.length, count)) {
                    result.put("code", "-1");
                    result.put("msg", "该级别下的随机code码已使用完毕,不可创建子级code码！");
                    return result;
                }
            }
            result.put("code", "1");
            result.put("msg", statisticCode);
        }
        return result;
    }


    @RequiresPermissions("sys:statisticCode:edit")
    @RequestMapping("getUserMenu")
    @ResponseBody
    public Object getUserMenu() {
        Map<String, Object> result = getResult();
        result.put("code", 1);
        return result;
    }


    public Map<String, Object> getResult() {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("code", "-1");
        result.put("msg", "该code码不能创建子级code码！");
        return result;
    }

}
